/* USER CODE BEGIN Header */
/* you can remove the copyright */
/*
 *  Copyright 2020-2024 Yuntu Microelectronics co.,ltd
 *  All rights reserved.
 * 
 *  YUNTU Confidential. This software is owned or controlled by YUNTU and may only be
 *  used strictly in accordance with the applicable license terms. By expressly
 *  accepting such terms or by downloading, installing, activating and/or otherwise
 *  using the software, you are agreeing that you have read, and that you agree to
 *  comply with and are bound by, such license terms. If you do not agree to be
 *  bound by the applicable license terms, then you may not retain, install,
 *  activate or otherwise use the software. The production use license in
 *  Section 2.3 is expressly granted for this software.
 * 
 * @file main.c
 * @brief 
 * 
 */

/* USER CODE END Header */
#include "Mcal.h"
/* Includes ------------------------------------------------------------------*/

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "Platform_Types.h"
#include "Spi.h"
#include "pSIP_Spi.h"
#include "string.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define SetTempPdu(PduHandle, Len, Id)      \
do {                                        \
    TempPduInfo.swPduHandle = PduHandle;    \
    TempPduInfo.id = Id;                    \
    TempPduInfo.length = Len;               \
}                                           \
while(0);

#define DEBUG_RX 1
#define DEBUG_TX 0
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */

//报文要发送的数据
uint8 sduData16[16] = {
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F
};

//LPDU的结构体变量
Can_PduType TempPduInfo = {
    .swPduHandle = 60U,
	.id = 0x000U,
    .length = 16U,
    .sdu = sduData16,
};

typedef struct 
{
    uint8 length;           /*!< Length of Can L-PDU in bytes */
    Can_IdType id;          /*!< Can ID of Can L-PDU */
    uint8 *sdu;  
}CANRx;

Can_PduType CanTxHandleConfig[] = {
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x1B1 , .id = 0x1B1 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 8   , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x1B2 , .id = 0x1B2 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 8   , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x351 , .id = 0x351 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 8   , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x5C1 , .id = 0x5C1 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 8   , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x2F7 , .id = 0x2F7 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 8   , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x381 , .id = 0x381 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 8   , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x6CB , .id = 0x6CB | CAN_ID_TYPE_FD_FRAME_MASK, .length = 8   , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x7C4 , .id = 0x7C4 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 8   , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x784 , .id = 0x784 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 8   , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x7DF , .id = 0x7DF | CAN_ID_TYPE_FD_FRAME_MASK, .length = 8   , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x235 , .id = 0x235 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 16  , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x2C0 , .id = 0x2C0 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 16  , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x1E3 , .id = 0x1E3 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 16  , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x2F3_H , .id = 0x2F3 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 16  , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x2F3_L , .id = 0x2F3 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 16  , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x357 , .id = 0x357 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 32  , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x3A3 , .id = 0x3A3 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 64  , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x6EB , .id = 0x6EB | CAN_ID_TYPE_FD_FRAME_MASK, .length = 64  , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x181 , .id = 0x181 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 64  , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x3A4 , .id = 0x3A4 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 64  , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x5E4 , .id = 0x5E4 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 64  , .sdu = sduData16},
    { .swPduHandle = CanConf_CanHardwareObject_CAN0_Tx_0x6EC , .id = 0x6EC | CAN_ID_TYPE_FD_FRAME_MASK, .length = 64  , .sdu = sduData16},
};         


Can_PduType Can1TxHandleConfig[] = {
    {.swPduHandle = CanConf_CanHardwareObject_CAN1_Tx_0x1B0 , .id = 0x1B0 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 8 , .sdu = sduData16 },
    {.swPduHandle = CanConf_CanHardwareObject_CAN1_Tx_0x2A3 , .id = 0x2A3 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 16 , .sdu = sduData16 },
    {.swPduHandle = CanConf_CanHardwareObject_CAN1_Tx_0x285 , .id = 0x285 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 32 , .sdu = sduData16 },
    {.swPduHandle = CanConf_CanHardwareObject_CAN1_Tx_0x1F9 , .id = 0x1F9 | CAN_ID_TYPE_FD_FRAME_MASK, .length = 64 , .sdu = sduData16 }
};

static volatile boolean DmaComplete = {FALSE};
static volatile uint32 IrqCount = 0;
static volatile uint32 IrqErrorCount = 0;

static Spi_DataBufferType SPI0ChannelTxSrcData[64] = {0};//spi0 channel 0要发送的数据
static Spi_DataBufferType SPI0ChannelRxDecData[64] = {0};

static uint8 CAN0_RxData[64] = {0}; //CAN0接收64字节数据
static uint8 CAN0_FIFORxData[64] = {0}; //CAN0接收64字节数据
static uint8 CAN1_RxData[64] = {0}; //CAN1接收64字节数据

static uint8 f_i = 0;
/* USER CODE END PV */

/* Private function declare --------------------------------------------------*/
/* USER CODE BEGIN PFDC */
/* USER CODE END PFDC */
static void Board_Init(void);

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void Delay_1ms(uint32 Ms);
void DmaChannel0Callback(void *Parameter);
void DmaChannel0ErrorCallback(void *Parameter);

/* USER CODE END 0 */


/**
 * @brief  The application entry point.
 * @retval int
 */
int main(void)
{
    /* USER CODE BEGIN 1 */
    
    Mcu_Init(&Mcu_Config);
    Mcu_InitClock(0);
#if (MCU_NO_PLL == STD_OFF)
    while ( MCU_PLL_LOCKED != Mcu_GetPllStatus() )
    {
        /* Busy wait until the System PLL is locked */
    }
    Mcu_DistributePllClock();
#endif
    /* USER CODE END 1 */ 
    Board_Init();
    /* USER CODE BEGIN 2 */
    Can_SetControllerMode(CanConf_CanController_CAN0, CAN_CS_STARTED);
    Can_SetControllerMode(CanConf_CanController_CAN1, CAN_CS_STARTED);
    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    uint32 Cnt = 0U;
    boolean RLEDState = STD_LOW;
    
    /* 设置SPI的传输模式为中断模式 */
    Spi_SetAsyncMode(SPI_INTERRUPT_MODE);
    /* 设置channel要发送的数据源和接收数据地址 */
    Spi_SetupEB(SpiConf_SpiChannel_SpiChannel_0, &SPI0ChannelTxSrcData[0], &SPI0ChannelRxDecData[0], 10);
    Spi_SetupEB(SpiConf_SpiChannel_SpiChannel_1, &SPI0ChannelTxSrcData[10], &SPI0ChannelRxDecData[10], 10);
    
    while (1)
    {
        if (Cnt % 500 == 0)
        {
            RLEDState = !RLEDState;
            Dio_WriteChannel(DioConf_DioChannel_LED_R , RLEDState);   
#if DEBUG_TX            
            Can_Write(CanTxHandleConfig[f_i].swPduHandle , &CanTxHandleConfig[f_i]);
            if ((f_i++) > sizeof(CanTxHandleConfig)/sizeof(Can_PduType))
            {
                f_i = 0;
            }
#endif
#if DEBUG_RX
            Can_Write(Can1TxHandleConfig[f_i].swPduHandle , &Can1TxHandleConfig[f_i]);
            if ( (f_i++) > sizeof(Can1TxHandleConfig)/sizeof(Can_PduType) )
            {
                f_i = 0;
            }
#endif
        }
        if (Cnt % 1000 == 0)
        {
            //CAN0循环发送报文测试使用
            //for (f_i = 0; f_i < sizeof(CanTxHandleConfig)/sizeof(Can_PduType) ; f_i++)
            //{
                //Can_Write(CanTxHandleConfig[f_i].swPduHandle , &CanTxHandleConfig[f_i]);
            //} 
            
            
            //SPI0发送报文初始化
            for (uint32 i = 0; i < sizeof(SPI0ChannelTxSrcData)/sizeof(Spi_DataBufferType); i++)
            {
                SPI0ChannelTxSrcData[i] = i+1 ;
            }

            //Spi_WriteIB(SpiConf_SpiChannel_SpiChannel_0, SPI0_Channel0_TxData);
            //实现SPI0异步通信的方式一
            //if(Spi_GetSequenceResult(SpiConf_SpiSequence_SpiSequence_0) == SPI_SEQ_OK)
            //{
            //    Spi_ReadIB(SpiConf_SpiChannel_SpiChannel_0, &SPI0_Channel0_RxData[0]);
            //}
            /* Sequence_0中调用job，job按照配置调用已有的channel */
            Spi_AsyncTransmit(SpiConf_SpiSequence_SpiSequence_0);
        }
        
        Cnt++;
        Delay_1ms(1);
        /* USER CODE END WHILE */
        /* USER CODE BEGIN 3 */
    }
    /* USER CODE END 3 */
}

static void Board_Init(void)
{
    Port_Init(&Port_Config);
    Can_Init(&Can_Config);
    CddDma_Init(&CddDma_Config);
    Spi_Init(NULL_PTR);
    Platform_Init(NULL_PTR);
}

/* USER CODE BEGIN 4 */

void Delay_1ms(uint32 Ms)
{
    while (Ms > 0)
    {
        --Ms;
        for (uint16 Cnt = 0; Cnt < 5700; ++Cnt)
        {
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
        }
    }
}

boolean CanReceiveCallOut(uint8 Hrh, Can_IdType CanId, uint8 CanDataLegth, const uint8* CanSduPtr )
{
    switch (CanId)
    {
    case  CanConf_CanController_CAN0 :
        /* code */
        break;
    
    case  0x181 | CAN_ID_TYPE_FD_FRAME_MASK:
        memcpy(CanSduPtr,CAN1_RxData,CanDataLegth);
        /* code */
        break;
    default:
        break;
    }
    return TRUE;
}
//实现SPI0异步通信的方式二
void SPI0Sequence0_CallBack(void)
{
    //Spi_ReadIB(SpiConf_SpiChannel_SpiChannel_0, &SPI0_Channel0_RxData[0]);
    /* 直接处理SPI0ChannelRxDecData中的数据 */
}


/* USER CODE END 4 */
